Skip to content

fix(ios): keep a zoomed ScrollView usable when its content size changes - #58498

Open
mifi wants to merge 1 commit into
react:mainfrom
mifi:fix-zoomed-scrollview-resize
Open

fix(ios): keep a zoomed ScrollView usable when its content size changes#58498
mifi wants to merge 1 commit into
react:mainfrom
mifi:fix-zoomed-scrollview-resize

Conversation

@mifi

@mifi mifi commented Sep 12, 2026

Copy link
Copy Markdown

Summary:

RCTScrollViewComponentView's _containerView is also the view UIScrollView zooms (viewForZoomingInScrollView:), so while the user is pinch-zoomed in it carries a scale transform. On every content size change updateState:oldState: assigned _containerView.frame, which is undefined behavior for a view with a non-identity transform (in practice UIKit shrinks the view's bounds by the zoom scale), and it also handed the unzoomed size to the UIScrollView as contentSize.

Visible result: pinch-zoom into a ScrollView, then change its size (rotate the device, or change the layout around it). The scrolled position jumps, and the content can no longer be zoomed all the way out; it stays stuck in a corner until the user zooms out and resizes again.

This lays the container out through bounds and center instead, and gives the scroll view the zoomed content size, which is what UIScrollView itself keeps contentSize at while zooming. With zoomScale == 1 the result is identical to before. In RTL, where the container carries a flip transform, bounds/center produce the same frame the old assignment did.

Changelog:

[IOS] [FIXED] - Pinch-zoomed ScrollView no longer breaks (position jump, cannot zoom back out) when its size changes

Test Plan:

  1. Run the reproducer at https://github.com/mifi/reproducer-react-native (a zoomable ScrollView whose height changes on a button press, or rotate the device).
  2. Zoom in, pan, resize. Before: position jumps and the content can no longer be zoomed out fully. After: zoom scale is kept and the content can be zoomed back out to fill the ScrollView.
  3. Unzoomed ScrollViews (RNTester ScrollView examples, including RTL) behave as before.

Generated by Claude Code

`RCTScrollViewComponentView`'s `_containerView` is also the view that
UIScrollView zooms (`viewForZoomingInScrollView:`), so while the user is
pinch-zoomed in it carries a scale transform. On every content size
change `updateState:oldState:` assigned `_containerView.frame`, which is
undefined behavior for a view with a non-identity transform (UIKit ends
up shrinking the view's bounds by the zoom scale), and it also passed the
unzoomed size to the UIScrollView as `contentSize`.

The visible result: pinch-zoom into a ScrollView, then change its size
(rotate the device, or change the layout around it). The scrolled
position jumps, and the content can no longer be zoomed all the way out;
it stays stuck in a corner until the user zooms out and resizes again.

Lay the container out through `bounds` and `center` instead, and give
the scroll view the zoomed content size, which is what UIScrollView
itself keeps `contentSize` at while zooming.
@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Sep 12, 2026
@facebook-github-tools facebook-github-tools Bot added the Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. label Sep 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant